#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include "cJSON.h"
#include "msg_queue_peer.h"
#define N 256
char ver[256]="v1.0.1";
char rec_ver[256]="";
int main(int argc, char const *argv[])
{
    int broadfd;

    // 创建一个 UDP socket
    broadfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (broadfd < 0)
    {
        perror("sock err");
        return -1;
    }

    // 绑定 UDP 套接字 (0.0.0.0:8888)
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(9876); // UDP 端口 8888
    addr.sin_addr.s_addr = INADDR_ANY;

    int addrlen = sizeof(addr);

    if (bind(broadfd, (struct sockaddr *)&addr, addrlen) < 0)
    {
        perror("bind err");
        return -1;
    }

    ssize_t len;
    char buf[N] = {0};
    struct sockaddr_in cliaddr;

    // 接收 "hello world" 广播
    bzero(buf, N);
    len = recvfrom(broadfd, buf, N, 0, (struct sockaddr *)&cliaddr, &addrlen);
    if (len < 0)
    {
        perror("recvfrom failed");
        return -1;
    }

    // 检查是否是 "hello world"
    if (strcmp(buf, "hello world") != 0)
    {
        printf("Received invalid message: %s\n", buf);
        return -1;
    }
    printf("Received: %s\n", buf);

    // 回复 "yes" 到发送方（明确指定端口 8888）
    cliaddr.sin_port = htons(8888); // 强制回复到 8888 端口
    int bytes_sent = sendto(broadfd, "yes", 4, 0, (struct sockaddr *)&cliaddr, addrlen);
    if (bytes_sent < 0)
    {
        perror("sendto failed");
        return -1;
    }
    printf("Reply sent to %s:%d\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));

    // 创建 TCP socket（使用不同端口 8889）
    int tcpfd = socket(AF_INET, SOCK_STREAM, 0);
    if (tcpfd < 0)
    {
        perror("TCP sock err");
        return -1;
    }

    struct sockaddr_in tcp_addr, caddr;
    tcp_addr.sin_family = AF_INET;
    tcp_addr.sin_port = htons(8888);
    tcp_addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(tcpfd, (struct sockaddr *)&tcp_addr, addrlen) < 0)
    {
        perror("TCP bind err");
        return -1;
    }

    // 监听 TCP
    if (listen(tcpfd, 5) < 0)
    {
        perror("listen err");
        return -1;
    }

    printf("TCP server waiting on port 8888...\n");
    int clifd = accept(tcpfd, NULL, NULL);
    if (clifd < 0)
    {
        perror("accept err");
        return -1;
    }
    printf("client ip : %s  port:%d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
    printf("New TCP connection accepted\n");
    char buf1[1024] = {};
    while (1)
    {
        //FILE *json_file = fopen("data.json", "w");
        int ret = recv(clifd, buf1, sizeof(buf1) - 1, 0);
        if (ret < 0)
        {
            perror("recv err");
            return -1;
        }
        else if (ret == 0)
        {
            printf("client exit\n");
            break;
        }
        buf1[ret] = '\0';
        // if (fwrite(buf1, 1, sizeof(buf1), json_file) != ret)
        // {
        //     perror("fwrite err");
        //     fclose(json_file);
        //     return -1;
        // }
        // fclose(json_file);
        printf("recv:%s 6666666666 \n", buf1);


        cJSON *root = cJSON_Parse(buf1);
        if (NULL == root)
        {
            printf("parse err\n");
            return -1;
        }
        // 获取root节点上名字叫ver的子节点
        cJSON *item = cJSON_GetObjectItem(root, "type");
        
        printf("type = %d\n", item->valueint);
        // 获取root节点上名字叫data的子节点
        cJSON *data = cJSON_GetObjectItem(root, "data");
        if (data && data->type == cJSON_Object) {
        // 解析 "data" 下的字段
        cJSON *ver = cJSON_GetObjectItem(data, "ver");
          strncpy(rec_ver, ver->valuestring, sizeof(rec_ver) - 1);  // 安全复制
            rec_ver[sizeof(rec_ver) - 1] = '\0';  // 确保字符串终止
        cJSON *file_name = cJSON_GetObjectItem(data, "file_name");
        cJSON *file_len = cJSON_GetObjectItem(data, "file_len");
        cJSON *md5 = cJSON_GetObjectItem(data, "md5");

        if (ver && ver->type == cJSON_String) {
            printf("ver = %s\n", ver->valuestring);
        }
        if (file_name && file_name->type == cJSON_String) {
            printf("file_name = %s\n", file_name->valuestring);
        }
        if (file_len && file_len->type == cJSON_Number) {
            printf("file_len = %d\n", file_len->valueint);
        }
        if (md5 && md5->type == cJSON_String) {
            printf("md5 = %s\n", md5->valuestring);
        }
    } else {
        printf("data field missing or invalid!\n");
    }
    if (strstr(ver,rec_ver)){

        int ver_send = send(clifd, "no", 3, 0);
        printf("不需要升级\n");
    } else {
    send(clifd, "yes", 3, 0);  // 确认需要升级

    // 接收文件头（格式：文件名|大小）
    char header[256];
    int len = recv(clifd, header, sizeof(header), 0);
    header[len] = '\0';
    
    char *filename = strtok(header, "|");
    long filesize = atol(strtok(NULL, "|"));

    // 按实际文件名保存（而非固定a.c）
    FILE *file = fopen(filename, "wb");
    if (!file) {
        perror("fopen error");
        send(clifd, "error", 6, 0);
        return -1;
    }

    // 接收文件内容
    char buffer[4096];
    long total_received = 0;
    while (total_received < filesize) {
        ssize_t bytes = recv(clifd, buffer, sizeof(buffer), 0);
        if (bytes <= 0) break;  // 网络中断
        fwrite(buffer, 1, bytes, file);
        total_received += bytes;
        printf("已接收: %ld/%ld bytes\n", total_received, filesize);
    }

    fclose(file);
    printf("文件保存为: %s\n", filename);

    cJSON *root = cJSON_CreateObject();
    cJSON_AddNumberToObject(root, "type", 2);
    
    cJSON *data = cJSON_CreateObject();
    cJSON_AddStringToObject(data, "trans_success", "true");
    cJSON_AddItemToObject(root, "data", data);

    char *json_str = cJSON_PrintUnformatted(root);
    send(clifd, json_str, strlen(json_str), 0);
    printf("数据包接收成功\n");
    // 释放内存
    cJSON_Delete(root);
    
    // 第二次发送：升级结果JSON（type=3）
    root = cJSON_CreateObject();
    cJSON_AddNumberToObject(root, "type", 3);
    data = cJSON_CreateObject();
    cJSON_AddStringToObject(data, "update_success", "true"); 
    cJSON_AddItemToObject(root, "data", data);

    json_str = cJSON_PrintUnformatted(root);
    send(clifd, json_str, strlen(json_str), 0);
    
    cJSON_Delete(root);
    free(json_str);
    printf("硬件升级成功\n");
}
        // 释放整棵树的内存
        cJSON_Delete(root);
    }
    close(clifd);
    close(tcpfd);
    close(broadfd);

    return 0;
}